#主业务层 可以脱离HASS独立运行 重启3.2秒
import sys
import logging
import socket
import time
from threading import Thread
import voluptuous as vol
import os


# Import the device class from the component that you want to support
from homeassistant.components.light import ATTR_BRIGHTNESS,ATTR_BRIGHTNESS_PCT, Light, PLATFORM_SCHEMA,SUPPORT_BRIGHTNESS,SUPPORT_TRANSITION,SUPPORT_EFFECT,SUPPORT_FLASH
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
import homeassistant.helpers.config_validation as cv

# Home Assistant depends on 3rd party packages for API specific code.
#sys.path.append('C:\\Users\\贾\\AppData\\Local\\Programs\\Python\\Python36-32\\Lib\\site-packages\\homeassistant\\components\\light')

_LOGGER = logging.getLogger(__name__)

# Validation of the user's configuration
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Required(CONF_HOST): cv.string,
})


###################################################自定义变量
log=_LOGGER.warning
err=_LOGGER.error
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
from glab import *
import albh
#log(os.path.abspath(os.path.dirname(__file__)))

class light_hub():#实现方法

    def __init__(self,name,ip='192.168.1.7'):
        
        self._ip_addr = ip
        self.brightness = 0
        self._state = False
        self._socket = None
        self._threads = []
        self.name = name


    
    

    def send(self, data):
        try:
            log("发送 -->> %s",data)
            self._socket.send(Hexs2Decs(data))

        except socket.timeout:
            err("网络连接失败 IP:%s", self._ip_addr)
            return

        except OSError as e:
            if e.errno == 32:  # Broken pipe
                err("OSError 32 raise, Broken pipe", exc_info=e)

 #   00 03 00 03 00 01 75 DB =发到IP=
 #   00 03 00 03 01 01 74 4B =发到IP=

    def dim(self,id=0,port=0,liangdu=0):#liangdu=0~100
        liangdu=int(liangdu)
        self.send(hex(id)+" 06 80 " +iif(port==0,"11","21") +" "+("%02X"%liangdu)+" 03")

    def islive1(self):
        self.send("00 03 10 02 FF FF")
    def turn_on(self,id=0,port=0,liangdu=0):#liangdu=0~100
        self.send(hex(id)+" 03 00 03 "+"%02X"%(port)+" 01")
        
        
    def turn_off(self,id=0,port=0):
        self.send(hex(id)+" 03 00 03 "+"%02X"%(port)+" 00")
        #self.send("FF 01 FF 00 00 20")
        #self.send("FF 02 FF 00 00 03")


    def _creat_socket(self):
        if self._socket is not None:
            self._socket.close()
            self._socket = None
        try:
            self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self._socket.settimeout(60)
            self._socket.connect((self._ip_addr,20108))
            self.send("FF FE FD FC FB F8")
        except:
            err('网络连接失败')

    def listen(self):
         self._creat_socket()
         self._listening = True
         thread = Thread(target=self._listen_to_msg, args=())
         self._threads.append(thread)
         thread.daemon = True
         thread.start()

    def _listen_to_msg(self):
         
         scal=0
         rec_tol = 0
         data_tail=[]#进过8位格式化的数据
         data1=[]

         while self._listening:
             if self._socket is None:
                 continue
             try:
                     rec_tol+=1
                     data = self._socket.recv(1024)#
                     data1=data_tail+list(data)#上次的尾巴 加上这次不完整的数据包  组成一个完整的数据包
                     scal=len(data1)
                     if data_tail!=[] and (scal%8>0):#当有尾巴 而且补齐后还不是8的整数倍  那就报警
                      err("数据包丢失")
                      data_tail.clear()
                      continue
                     index=0
                     while scal>=8:
                       index=index+8
                       t="%02X %02X %02X %02X %02X %02X %02X %02X"%(data1[0],data1[1],data1[2],data1[3],data1[4],data1[5],data1[6],data1[7])
                       log("接收"+ str(rec_tol) + "="+t+ "=" + albh.exp(t))
                       scal=scal-8
                     #raise Exception("Invalid level!",0)
                     data_tail=data1[index:]#h获取尾巴 当然大部分情况是None 
                     #log("data_tail="+str(data_tail))
             except ConnectionResetError:
                 err("重新连接")
                 self._creat_socket()
                 continue
                 
             except socket.timeout as e:
                 self.islive1()
                 continue
         
             except Exception as e:
                 err("错误:" + str(e))
                 continue

class AwesomeLight(Light):#所有模块的公共接口 每个灯都有一个独立的实例
    """Representation of an Awesome Light."""

    def __init__(self,port,IoName,light,leixin=0,id=0):

        self._light = light#函数的赋值  传递的是地址
        self._name =IoName #iif(leixin==1,"调光","灯")+"%02d"%(int(IoName[4:]))#每个IO端口的名字
        self._state = 0#注意  变量= 那么只是普通个赋值
        self._brightness = 200
        self.port =  port
        self._id =  id
        #renew=self.schedule_update_ha_state()
        self._leixin =  leixin
        #注意 因为面向灯控网关的连接只有一个线程（实例），因此需要提前做好表格
        #比如 ID2id[011]=2 模块ID02上的第1路 对应 HASS中的第2个灯
        albh.ID2id[hex(id)+ str(port)]=len(lights)#注意调光只有2路的 


        
    @property
    def supported_features(self):

        a=0
        if(self._leixin==1):a=int(SUPPORT_BRIGHTNESS |SUPPORT_TRANSITION)

        return a

    @property
    def name(self):
        return self._name

    @property
    def brightness(self):#
        #err("brightness?"+self._name+"=liangdu=" + str(self._brightness))
        return self._brightness

    @property
    def is_on(self):#查询步骤2 上传灯有没开 如果开的那返回true 
        #log("ISON?"+self._name+ "=self._state " + str(self._state))
        return self._state

    def turn_on(self, **kwargs):#注意 即使是调光 他在直接开的时候 是不带亮度指令的
        self._state = True
        Read_BRIGHTNESS=kwargs.get(ATTR_BRIGHTNESS, 0)
        #err("Read_BRIGHTNESS"+str(Read_BRIGHTNESS))
        
       
        if(Read_BRIGHTNESS!=0 or self._leixin):#当为0的时候 说明没有亮度的信息
          if(Read_BRIGHTNESS!=0):self._brightness =Read_BRIGHTNESS#当为0时候 说明不带亮度信息  那就用以前的吧
          self._light.dim(self._id,self.port,self._brightness/2.55)
        else:
          self._light.turn_on(self._id,self.port)

    def turn_off(self, **kwargs):
    
        self._state = False
        if(self._leixin):self._light.dim(self._id,self.port,0)
        else:self._light.turn_off(self._id,self.port)

    def update(self):#查询步骤1 刷新变量
        pass
        #self._light.islive()
        #log("UP?"+self._name+ "=" + str(self._state))
        #self._state =      self._light._state#灯开着吗
        #self._brightness = self._light.brightness#可能是手动改了亮度 未通知系统 
        #self.schedule_update_ha_state()
        #hass.services.call(DOMAIN, SERVICE_TURN_ON, data)
        #_LOGGER.error("brightness="+str(self._light.brightness))
#self._brightness = round(255 * (int(bright) / 100))


def setup_platform(hass, config, add_devices, discovery_info=None):
    """Setup the Awesome Light platform."""

    # Assign configuration variables. The configuration check takes care they are
    # present.
    host = config.get(CONF_HOST)
    #username = config.get(CONF_USERNAME)
    #password = config.get(CONF_PASSWORD)
    lights.clear()
    log("=======奥乐巴赫加载成功=============================")
    conn=light_hub("Aolebach1")#申请一个实例 运行一次init 全局只有一个连接 默认192.168.1.7:20108

    lights.append(AwesomeLight(0,"AL_P01",conn))
    lights.append(AwesomeLight(1,"AL_P02",conn))
    lights.append(AwesomeLight(2,"AL_P03",conn))
    lights.append(AwesomeLight(3,"AL_P04",conn))
    lights.append(AwesomeLight(4,"AL_P05",conn))
    lights.append(AwesomeLight(5,"AL_P06",conn))
    lights.append(AwesomeLight(0,"AL_P07",conn,0,2))
    lights.append(AwesomeLight(1,"AL_P08",conn,0,2))
    lights.append(AwesomeLight(2,"AL_P09",conn,0,2))
    lights.append(AwesomeLight(3,"AL_P10",conn,0,2))
    lights.append(AwesomeLight(4,"AL_P11",conn,0,2))
    lights.append(AwesomeLight(5,"AL_P12",conn,0,2))
    lights.append(AwesomeLight(0,"AL_T13",conn,1,4))
    lights.append(AwesomeLight(1,"AL_T14",conn,1,4))
    lights.append(AwesomeLight(0,"AL_T15",conn,1,5))
    lights.append(AwesomeLight(1,"AL_T16",conn,1,5))

    add_devices(lights, True)
    
    conn.listen()
if __name__ == '__main__':
 log=print
 light_hub("jia1"+ __name__)

#(<homeassistant.core.HomeAssistant object at 0x03D2FF70>, 
#OrderedDict([
#('platform', 'awesomelights'),
#('host', 'HOST_HERE'),
#('username', 'USERNAME_HERE'),
#('password', 'PASSWORD_HERE_')
#]),
#<bound method EntityPlatform._schedule_add_entities of <homeassistant.helpers.entity_platform.EntityPlatform object at 0x04A39810>>,
#None)
#
#def setup_platform(hass, config, add_devices, discovery_info=None):

#    host = config.get(CONF_HOST)
#    username = config.get(CONF_USERNAME)
#    password = config.get(CONF_PASSWORD)
#    _LOGGER.warning(' AwesomeLight')
#    lights = []
#    lights.append(AwesomeLight('jiajundong'))
#    add_devices(lights, True)
